在OpenGL和OpenGL ES中使用自定义和通用顶点着色器属性

时间:2014-01-29 05:49:21

标签: opengl opengl-es glsl shader rendermonkey

由于在OpenGL中不推荐使用通用顶点属性,因此我尝试仅使用自定义属性重写顶点着色器。我没有为我工作。这是顶点着色器:

attribute vec3 aPosition;
attribute vec3 aNormal;

varying   vec4 vColor;

vec4 calculateLight(vec4 normal) {
    // ...
}

void main(void) {
    gl_Position = uProjectionMatrix * uWorldViewMatrix * vec4(aPosition, 1);
    vec4 rotatedNormal = normalize(uWorldViewMatrix * vec4(aNormal, 0));
    vColor = calculateLight(rotatedNormal);
}

这在OpenGL ES 2.0中完美运行。但是,当我尝试将它与OpenGL一起使用时,我会看到黑屏。如果我将aNormal更改为通用gl_Normal,那么一切正常(请注意aPosition在两种情况下都能正常工作,而且我不必使用gl_Vertex)。

我做错了什么?

我使用RenderMonkey来测试着色器,并在其中使用适当的属性名称(aPosition和aNormal)设置流映射。也许它与属性索引有关,因为我将所有这些都设置为0?此外,这是RenderMonkey文档中关于在“流映射”中设置自定义属性名称的内容:

  

“属性名称”字段显示可以使用的默认名称   在着色器编辑器中用于引用该流。在OpenGL ES效果中,改变了   name应该用于引用流;但是,在DirectX或OpenGL效果中,   新名称在着色器编辑器中没有任何影响

我想知道此问题是否特定于RenderMonkey或OpenGL本身?为什么aPosition仍然适用?

1 个答案:

答案 0 :(得分:1)

属性索引应该是唯一的。在链接程序之前,可以通过glBindAttribLocation 告诉OpenGL使用特定索引。无论哪种方式,通常的方法是使用glGetAttribLocation查询索引。听起来像RenderMonkey让你选择,在这种情况下你是否尝试将它们分开?

我之前看到固定函数渲染交叉到顶点属性,其中glVertexPointer可以在第一个属性未绑定时结束第一个属性(我不知道这是否可以再现)。 / p>

在尝试使用属性和固定函数名称时,我也看到了一些奇怪的东西。不调用glBindAttribLocation,我编译以下着色器:

attribute vec4 a;
attribute vec4 b;
void main()
{
    gl_Position = gl_Vertex + vec4(gl_Normal, 0) + a + b;
}

我得到以下位置(通过glGetActiveAttrib):

a: 1
b: 3
gl_Vertex: -1
gl_Normal: -1

在进行实验时,似乎使用gl_Vertex占用索引0gl_Normal占用索引2(即使未报告)。我想知道你是否在aPositionaNormal之间输入了一个填充属性(不要忘记在输出中使用它或者它会被编译掉)使它工作。

在这种情况下,位置数据可能最后简单地绑定到零位置。但是,aNormal的黑屏表示没有任何约束(在这种情况下,它始终为{0, 0, 0})。这有点不那么一致 - 如果法线与你期望某种颜色的位置相同的数据,如果不是正确的颜色,则法线会有位置数据。

  

允许应用程序绑定多个用户定义的属性   变量到相同的通用顶点属性索引。这就是所谓的   别名,仅在其中一个别名属性时才允许使用   在可执行程序中处于活动状态,或者如果没有通过着色器的路径   消耗了一组属性的多个属性   同一地点。

我的感觉是,RenderMonkey只使用glVertexPointer / glNormalPointer而不是属性,我会将正常和位置绑定到正常或位置数据,因为你说两个索引是零。

  

在DirectX或OpenGL效果中,新名称在着色器编辑器中没有任何影响

也许这意味着“命名流”在非ES OpenGL版本中根本不可用?

这是不相关的,但在最近的OpenGL-GLSL版本中,需要#version个数字,属性使用关键字in