似乎glsl编译器优化了未使用的变量(删除)。
就我而言,我使用了变量,但是glGetUniformLocation
返回-1
rgbScene.addRenderStage(
[&obj = std::as_const(model)](Camera* cam) {
auto& mesh = std::get<Mesh>(obj);
auto& program = std::get<ShaderProgram>(obj);
glUseProgram(program);
glBindVertexArray(mesh.getData<VAO>());
int loc;
glUniformMatrix4fv(
loc = glGetUniformLocation(program, "proj_matrix"),
1, GL_FALSE,
glm::value_ptr(cam->getProjectionMatrix())
);
glUniformMatrix4fv(
loc = glGetUniformLocation(program, "view_matrix"),
1, GL_FALSE,
glm::value_ptr(cam->getViewMatrix())
);
glUniformMatrix4fv(
loc = glGetUniformLocation(program, "model_matrix"),
1, GL_FALSE,
glm::value_ptr(mesh.getModelMatrix())
);
glUniform3fv(
loc = glGetUniformLocation(program, "light_direction"),
1, glm::value_ptr(-(cam->getForward()))
);
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, mesh.getData<VertexData>());
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
glEnableVertexAttribArray(1);
glBindBuffer(GL_ARRAY_BUFFER, mesh.getData<NormalData>());
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
glDrawArrays(GL_TRIANGLES, 0, mesh.getSize());
glDisableVertexAttribArray(1);
glDisableVertexAttribArray(0);
});
我通过在Visual Studio 2019中逐行调试来检查变量loc
,最后glGetUniformLocation
返回-1
这是我的顶点着色器代码
#version 460 core
uniform mat4 proj_matrix;
uniform mat4 view_matrix;
uniform mat4 model_matrix;
uniform vec3 light_direction;
layout(location = 0) in vec3 pos;
layout(location = 1) in vec3 normal;
out VS_OUT
{
vec3 N;
vec3 L;
vec3 V;
} vs_out;
void main(void)
{
vec4 P = view_matrix * model_matrix * vec4(pos, 1.0);
vs_out.N = mat3(view_matrix * model_matrix) * normal;
vs_out.L = mat3(view_matrix) * (-light_direction);
vs_out.V = -P.xyz;
gl_Position = proj_matrix * P;
}
我尝试更改变量名称,但顺序不同...但是无法解决此问题
着色器中是否还有其他统一变量规则?
-编辑- 对于片段着色器,
#version 460 core
layout (location = 0) out vec4 color;
in VS_OUT
{
vec3 N;
vec3 L;
vec3 V;
} fs_in;
uniform vec3 diffuse_albedo = vec3(0.8, 0.3, 0.2);
uniform vec3 specular_albedo = vec3(0.7);
uniform float specular_power = 128.0;
void main(void)
{
vec3 N = normalize(fs_in.N);
vec3 L = normalize(fs_in.L);
vec3 V = normalize(fs_in.V);
vec3 R = reflect(-L, N);
vec3 diffuse = max(dot(N, L), 0.0) * diffuse_albedo;
vec3 specular = pow(max(dot(R, V), 0.0), specular_power) * specular_albedo;
color = vec4(diffuse + specular, 1.0);
// color = vec4(1.0,1.0, 1.0, 1.0);
}
答案 0 :(得分:1)
片段着色器输入N
,L
和V
变量也必须“已使用” 。
注意,活动资源是在链接程序时确定的。如果未使用片段着色器的输入,则在顶点着色器中设置相应输出变量的制服可能不会激活。
请参见OpenGL 4.6 Core Profile Specification - 7.3.1 Program Interfaces,第102页:
7.3.1程序接口
当程序对象成为当前渲染状态的一部分时,其可执行代码可以通过各种接口与其他GL管道阶段或应用程序代码进行通信。链接程序后,GL将为每个接口构建活动资源列表。活动资源的示例包括着色器代码使用的变量,接口块和子例程。着色器代码中引用的资源被认为是活动的,除非编译器和链接器可以最终确定它们对程序的可执行代码产生的结果没有可观察的影响。例如,如果变量已声明但未在可执行代码中使用,仅在永远不会执行的if语句的子句中使用,仅在从未调用的函数中使用或仅在临时计算中使用,则可能被视为无效对任何着色器输出没有影响的变量。如果编译器或链接器无法做出确定的决定,则着色器代码引用的任何资源都将被视为活动资源。任何接口的活动资源集都取决于实现,因为它依赖于编译器和链接器执行的各种分析和优化
如果程序成功链接,则GL将根据链接生成的可执行代码生成活动资源列表。