【发布时间】:2014-08-14 07:29:00
【问题描述】:
编辑:请参阅最后关于该主题的新调查。
我的着色器出现了奇怪的行为。简而言之,我觉得很奇怪,要将单个浮点数从顶点着色器传递给片段着色器,我还必须传递一个假变量,我正在寻找这种行为的解释。
更多细节:我写了两个极简着色器
-
一个将一个浮点数(只有一个,这很重要)
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 );
}
我发现这更像是“破解”而不是解决方案。我应该怎么做才能正确解决这个问题?
就可以从顶点着色器传递到片段着色器的数据大小而言,是否存在“每个驱动程序制造商的最小阈值”?
编辑:
在阅读了 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);
【问题讨论】:
-
不,没有这样的最小值。我对您的描述的第一个猜测是您的客户端 GL 代码中的错误,尤其是属性和/或统一位置。
-
@derhass 感谢您的关注!我用属性和制服仔细检查了我在代码中所做的事情,并检查了这些位置是否都正常。这样做,我发现了更多关于这个问题的信息,它似乎与属性具有“0”位置的事实有关(根据规范这是合法的,非法位置是-1)。请参阅我在问题中的编辑以了解更多信息。我还复制了我在程序中执行的 gl 调用。
-
属性0本身没有问题。您是否在代码中的某处使用旧的
glVertex*或glVertexPointer调用?该内置顶点属性是别名属性 0。 -
@derhass 我的应用程序中唯一的 glVertex* 调用是 glVertexAttrib 和 glVertexAttribPointer。评论中的别名是什么意思?
-
我的意思是使用旧的、已弃用的
glVertex..和glVertexPointer命令将等同于使用属性索引为 0 的现代通用属性函数。但是由于您不使用那些旧的东西,这应该不是问题。
标签: opengl glsl parameter-passing shader gpu