c++ - 着色器统一要么优化不当要么找不到

标签 c++ opengl

我终于努力学习如何编写着色器,并且我对它们的工作原理有了相当不错的了解。问题是,我无法检索统一结构的统一位置。现在我知道你必须查询每个单独的内部成员的位置,我正在做,而且我也知道如果 GL 确定统一不影响最终输出,它就会被优化掉(老实说这不是丝毫没有坏事)。

问题是,它没有找到用于影响片段着色器输出的制服。

在我的着色器类中,我有一个名为“GetAndStoreUniformLocation”的函数(我喜欢用名称来描述 - 确保清楚该函数的作用)!这个函数只是抓取给定统一名称的位置并将其插入 map ,所以我不必在每一帧都查询 OpenGL 的位置(我不确定这可能会或可能不会优化多好...在这个阶段还处于试验阶段)。此功能适用于所有由标准类型组成的制服。

问题(TL;DR):

为什么我无法从着色器中检索“ Material ”制服成员的位置?它不应该被优化掉,我正在将“material.*”(其中 * 是成员名称)传递给 glGetUniformLocation()。

我觉得我可能遗漏了一些明显的东西,但我已经在 OpenGL 文档和其他人的类似问题的帖子上搜索过,到目前为止没有提供任何有用的东西,只有优化删除的建议制服,但是,我怀疑是这种情况,因为它正在输出中使用。

我已经尝试在加载、编译和链接着色器后直接调用 glGetUniformLocation(),用于矩阵制服(成功)和 Material 。*制服(失败)。

代码

加载着色器后,我激活它以便访问统一位置,然后调用:

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'.

,所以它肯定让所有其他制服都很好。但是“ Material ”无处可寻,但是,正如您在着色器代码中看到的那样,“ Material ”结构的内部成员用于照明,用于颜色的最终输出。是的,我完全知道代码可能不正确或未优化......但是当我放下样板时,我只需要在其中添加一堆东西以使其在基本级别上工作。 Lighting 在制作结构之前一直在工作(之前,我只是使用硬编码值)

最佳答案

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

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

关于c++ - 着色器统一要么优化不当要么找不到,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57893002/

相关文章:

c++ - C2248 - 将 QScopedPointer 传递给函数时无法访问私有(private)成员

c++ - 根据键字符串使用迭代器更改嵌套映射的 int 值

c++ - 使用 OpenCL 获取 OpenGL 缓冲区

c# - 一次在屏幕上显示多个实体的 OpenGL 游戏,使用什么语言?

c++ - glTexSubImage 会导致黑色纹理,而 glTexImage 效果很好

c++ - 如何更改 ListView 控件的 WndProc

c++ - 可以为了速度牺牲常量正确性吗?

c++ - boost mpl 将每个元素包装在一个集合中

c++ - opengl 堆栈 glViewport 奇怪的行为

c++ - 渲染多个对象时opengl闪烁