编辑:见文末有关该主题的新调查。
我的着色器一直在经历一个奇怪的行为。简而言之,我发现这是非常奇怪的,通过一个单一的浮动从顶点着色器到片段着色器,我也必须通过一个假变量,我正在寻找这种行为的解释。
在更多的细节:我写了两个极简的着色器
-
一个顶点着色器,传递一个浮点数(只有一个,这是重要的),
vertAlpha
,片段着色器,像这样:#version 150 uniform float alphaFactor; uniform mat4 cameramodel; in float vertAlpha; in vec3 vert; in vec3 vertScale; in vec3 trans; out float fragAlpha; void main() { fragAlpha = alphaFactor * vertAlpha; gl_Position = cameramodel * vec4( trans + ( vert * vertScale ), 1.0f ); }
-
和使用传入变量的片段着色器:
#version 150 in float fragAlpha; out vec4 finalColor; void main() { finalColor = vec4( 0.0f, 0.0f, 0.0f, fragAlpha ); }
但这不起作用,屏幕上没有出现任何东西,似乎在片段着色器中,fragAlpha保持它的初始化值为0,并忽略传递的值。
经过调查,我找到了一个"hack"来解决这个问题。我发现片段着色器"看到"fragAlpha的传递值只有当一个假的(未使用的)值与它一起传递(取决于平台(osx/NVidia GeForce 9400, Windows笔记本电脑/Intel HD Graphics), vec3或vec2是足够的)。
所以这个顶点着色器解决了这个问题:
#version 150
uniform float alphaFactor;
uniform mat4 cameramodel;
in vec3 vertFake;
in float vertAlpha;
in vec3 vert;
in vec3 vertScale;
in vec3 trans;
out float fragAlpha;
out vec3 fragFake;
void main()
{
fragAlpha = alphaFactor * vertAlpha;
fragFake = vertFake;
gl_Position = cameramodel * vec4( trans + ( vert * vertScale ), 1.0f );
}
我觉得这更像是一个"hack"而不是一个解决方案。我该怎么做才能正确解决这个问题?
在可以从顶点着色器传递到片段着色器的数据大小方面是否存在"每个驱动程序制造商最小阈值"?
编辑:看完derhass注释后,我回到我的代码,看看我是否做错了什么。
经过更多的调查,我发现这个问题不是固有的事实,我传递属性值片段着色器。我改变了顶点着色器中属性声明的顺序,看到具有"0"位置的属性(由glGetAttribLocation返回的位置)没有通过调用glVertexAttribute更新,它的值保持在0。
如果在所有其他属性之前声明"trans"属性,就会发生这种情况。在我的着色器中引入一个假属性只修复了这个问题,因为假属性占用了位置"0"。
在任何情况下,glGetError都不会返回任何错误。
我使用glDrawElements来渲染,与包含顶点位置的vbo,也许我使用它不充分…或者我的硬件不支持它?
为了给出更多的上下文,我在这里复制我对opengl的调用,用于设置和渲染:
设置:
GLuint vao, vbo;
glGenBuffers(1, &vbo);
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
GLfloat vertexData[] = {
// X Y Z
0.0f, 0.0f, 1.0f, // 0
1.0f, 0.0f, 1.0f, // 1
0.0f, 0.0f, 0.0f, // 2
1.0f, 0.0f, 0.0f, // 3
0.0f, 1.0f, 1.0f, // 4
1.0f, 1.0f, 1.0f, // 5
1.0f, 1.0f, 0.0f, // 6
0.0f, 1.0f, 0.0f // 7
};
glBufferData(GL_ARRAY_BUFFER, sizeof(vertexData), vertexData, GL_STATIC_DRAW);
GLint vert = glGetAttribLocation(p, "vert")
glEnableVertexAttribArray(vert);
glVertexAttribPointer(vert, 3, GL_FLOAT, GL_FALSE, 0, NULL);
glBindVertexArray(0);
渲染:
glUseProgram(p)
aphaFactor = glGetUniformLocation(p,"alphaFactor");
glUniform1f(alphaFactor, 1.0f);
cameramodel = glGetUniformLocation(p,"cameramodel");
glm::mat4 mat = gCamera.matrix();
glUniformMatrix4fv(cameramodel, 1, GL_FALSE, glm::value_ptr(mat); //
glBindVertexArray(vao);
GLubyte indices[36] =
{
3, 2, 6, 7, 6, 2, 6, 7, 4, 2, 4, 7, 4, 2, 0, 3, 0, 2, 0, 3, 1, 6, 1, 3, 1, 6, 5, 4, 5, 6, 5, 4, 1, 0, 1, 4
};
GLint trans = glGetAttribLocation(p, "trans");
GLint alpha = glGetAttribLocation(p, "vertAlpha");
GLint scale = glGetAttribLocation(p, "vertScale");
loop over many entities:
glVertexAttrib3f(trans, m_vInstTransData[offset], m_vInstTransData[offset + 1], m_vInstTransData[offset + 2]);
glVertexAttrib1f(alpha, m_vInstTransData[offset + 3]);
glVertexAttrib3f(scale, m_vInstTransData[offset + 4], m_vInstTransData[offset + 5], m_vInstTransData[offset + 6]);
glDrawElements(GL_TRIANGLES, sizeof(indices) / sizeof(GLubyte), GL_UNSIGNED_BYTE, indices);
end loop
glBindVertexArray(0);
您需要为此指定插值器,以防止相同原语更改的片段之间的插值:
out float fragAlpha;
in float fragAlpha;
为:
out flat float fragAlpha;
in flat float fragAlpha;
,因为float
是默认内插的。类似地,默认情况下mat3
不会被插入,如果你想插入它,那么使用smooth
而不是flat
…
如果我没记错的话,标量(int,float,double
)和向量(vec?,dvec?
)是默认插值的,矩阵(mat?
)不是。
不确定将在您的平面变量中设置哪个属性,我打赌是在原始通道的最后一个顶点上设置的一个…如果你需要在某个指定的顶点上进行计算,那么你应该将计算移到几何着色器中。