当我想在同一程序的不同着色器阶段使用统一时,如何分配明确的统一位置?
使用自动分配时,不同阶段的制服在标识符匹配时分配到同一位置。但是如何使用
layout (location = ...)
句法?
以下引用自:
https://www.opengl.org/wiki/Uniform_(GLSL)/Explicit_Uniform_Location
It is illegal to assign the same uniform location to two uniforms in the same shader or the same program. Even if those two uniforms have the same name and type, and are defined in different shader stages, it is not legal to explicitly assign them the same uniform location; a linker error will occur.
以下引用来自 GLSL 规范:
No two default-block uniform variables in the program can have the same location, even if they are unused, otherwise a compile-time or link-time error will be generated.
我正在使用 OpenGL 4.3。
由于大量阅读代码,我发现制服是未使用的。
这会导致以下情况:在 GTX 780 上,以下代码运行没有问题(尽管似乎不应该)。根据 GL_ARB_DEBUG_OUTPUT 扩展,在 Intel HD 5500 板载图形芯片上,代码在链接时产生 SHADER_ID_LINK 错误。它指出,制服位置与另一个制服重叠。
顶点着色器:
#version 430 core
layout(location = 0) in vec4 vPosition;
layout(location = 2) in vec4 vTexCoord;
layout(location = 0) uniform mat4 WorldMatrix; // <-- unused in both stages
out vec4 fPosition;
out vec4 fTexCoord;
void main() { ... }
片段着色器:
#version 430 core
in vec4 fPosition;
in vec4 fTexCoord;
layout(location = 0) out vec4 Albedo;
layout(location = 1) out vec4 Normal;
layout(location = 0) uniform mat4 WorldMatrix; // <-- unused in both stages
layout(location = 1) uniform mat4 InverseViewProjectionMatrix;
layout(location = 2) uniform samplerCube Cubemap;
void main() { ... }
然而,当使用制服时,没有问题发生。假设我对 GLSL 规范的解释是正确的,这似乎与预期不同。虽然,这正是我希望它运行的方式。
尽管如此,当不使用制服时,仍然存在重叠制服的问题。
最佳答案
见 complete GL+VAO/VBO+GLSL+shaders example in C++
GPU端:
#version 400 core
layout(location = 0) in vec3 pos;
400+
它肯定会起作用pos
设置为位置 0
CPU端:
// globals
GLuint vbo[4]={-1,-1,-1,-1};
GLuint vao[4]={-1,-1,-1,-1};
const GLfloat vao_pos[]=
{
// x y z //ix
-1.0,-1.0,-1.0, //0
+1.0,-1.0,-1.0, //1
+1.0,+1.0,-1.0, //2
-1.0,+1.0,-1.0, //3
-1.0,-1.0,+1.0, //4
+1.0,-1.0,+1.0, //5
+1.0,+1.0,+1.0, //6
-1.0,+1.0,+1.0, //7
};
// init
GLuint i;
glGenVertexArrays(4,vao);
glGenBuffers(4,vbo);
glBindVertexArray(vao[0]);
i=0; // VBO location
glBindBuffer(GL_ARRAY_BUFFER,vbo[i]);
glBufferData(GL_ARRAY_BUFFER,sizeof(vao_pos),vao_pos,GL_STATIC_DRAW);
glEnableVertexAttribArray(i);
glVertexAttribPointer(i,3,GL_FLOAT,GL_FALSE,0,0);
当您附加时
data
至 location
那么你需要设置
layout location
因为它在所有着色器中都相同,它在单个阶段中使用它。您不能将同一位置分配给多个 VBO 立即(即您复制的所有状态)。单级是指单个/一组
glDrawArrays/glDrawElements
在不更改着色器设置的情况下调用。如果您有更多的着色器程序阶段(不止一个片段/顶点/几何体...),那么可以为每个阶段设置不同的位置,但在每个阶段内,其所有着色器程序必须具有相同的位置设置。通过单阶段启动,您可以假设每个
glUseProgram(prog_id);
调用并以 glUseProgram(0);
结束或另一个阶段开始......[edit2] 这里是非 nVidia 驱动程序的制服
顶点着色器:
// Vertex
#version 400 core
#extension GL_ARB_explicit_uniform_location : enable
layout(location = 0) in vec3 pos;
layout(location = 2) in vec3 nor;
layout(location = 3) in vec3 col;
layout(location = 0) uniform mat4 m_model; // model matrix
layout(location =16) uniform mat4 m_normal; // model matrix with origin=(0,0,0)
layout(location =32) uniform mat4 m_view; // inverse of camera matrix
layout(location =48) uniform mat4 m_proj; // projection matrix
out vec3 pixel_pos; // fragment position [GCS]
out vec3 pixel_col; // fragment surface color
out vec3 pixel_nor; // fragment surface normal [GCS]
void main()
{
pixel_col=col;
pixel_pos=(m_model*vec4(pos,1)).xyz;
pixel_nor=(m_normal*vec4(nor,1)).xyz;
gl_Position=m_proj*m_view*m_model*vec4(pos,1);
}
片段着色器:
// Fragment
#version 400 core
#extension GL_ARB_explicit_uniform_location : enable
layout(location =64) uniform vec3 lt_pnt_pos;// point light source position [GCS]
layout(location =67) uniform vec3 lt_pnt_col;// point light source color&strength
layout(location =70) uniform vec3 lt_amb_col;// ambient light source color&strength
in vec3 pixel_pos; // fragment position [GCS]
in vec3 pixel_col; // fragment surface color
in vec3 pixel_nor; // fragment surface normal [GCS]
out vec4 col;
void main()
{
float li;
vec3 c,lt_dir;
lt_dir=normalize(lt_pnt_pos-pixel_pos); // vector from fragment to point light source in [GCS]
li=dot(pixel_nor,lt_dir);
if (li<0.0) li=0.0;
c=pixel_col*(lt_amb_col+(lt_pnt_col*li));
col=vec4(c,1.0);
}
这些是来自链接示例的重写着色器,其布局位置用于制服。你必须添加:
#extension GL_ARB_explicit_uniform_location : enable
为
400
配置文件使其工作在 CPU 端使用
glGetUniformLocation
照常id=glGetUniformLocation(prog_id,"lt_pnt_pos"); glUniform3fv(id,1,lt_pnt_pos);
id=glGetUniformLocation(prog_id,"lt_pnt_col"); glUniform3fv(id,1,lt_pnt_col);
id=glGetUniformLocation(prog_id,"lt_amb_col"); glUniform3fv(id,1,lt_amb_col);
glGetFloatv(GL_MODELVIEW_MATRIX,m);
id=glGetUniformLocation(prog_id,"m_model" ); glUniformMatrix4fv(id,1,GL_FALSE,m);
m[12]=0.0; m[13]=0.0; m[14]=0.0;
id=glGetUniformLocation(prog_id,"m_normal" ); glUniformMatrix4fv(id,1,GL_FALSE,m);
for (i=0;i<16;i++) m[i]=0.0; m[0]=1.0; m[5]=1.0; m[10]=1.0; m[15]=1.0;
id=glGetUniformLocation(prog_id,"m_view" ); glUniformMatrix4fv(id,1,GL_FALSE,m);
glGetFloatv(GL_PROJECTION_MATRIX,m);
id=glGetUniformLocation(prog_id,"m_proj" ); glUniformMatrix4fv(id,1,GL_FALSE,m);
或定义位置:
id=64; glUniform3fv(id,1,lt_pnt_pos);
id=67; glUniform3fv(id,1,lt_pnt_col);
id=70; glUniform3fv(id,1,lt_amb_col);
glGetFloatv(GL_MODELVIEW_MATRIX,m);
id= 0; glUniformMatrix4fv(id,1,GL_FALSE,m);
m[12]=0.0; m[13]=0.0; m[14]=0.0;
id=16; glUniformMatrix4fv(id,1,GL_FALSE,m);
for (i=0;i<16;i++) m[i]=0.0; m[0]=1.0; m[5]=1.0; m[10]=1.0; m[15]=1.0;
id=32; glUniformMatrix4fv(id,1,GL_FALSE,m);
glGetFloatv(GL_PROJECTION_MATRIX,m);
id=48; glUniformMatrix4fv(id,1,GL_FALSE,m);
看起来像 nVidia 编译器以不同的方式处理位置。如果它不能正常工作,请尝试 有问题的驱动程序的解决方法 为每个数据类型设置不同步骤的位置:
float,int,bool
double
vec3
vec4
dvec3
dvec4
mat3
mat4
关于OpenGL - 不同着色器阶段的显式统一位置,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32416889/