1

所以我在使用 2 个不同的着色器渲染时遇到问题。我目前正在渲染代表骰子的形状,我想要的是如果用户选择了骰子,它通过将骰子完全绘制为红色并稍微放大来绘制轮廓,然后在其上渲染适当的骰子。目前,某些骰子出于某种原因,将错误的骰子渲染为轮廓,而将正确的骰子渲染为正确的前景骰子。

我想知道他们是否没有以某种方式混淆他们的顶点数据。我不确定在openGL中是否允许这样做:

glGenBuffers(1, &_vertexBuffer);
glBindBuffer(GL_ARRAY_BUFFER, _vertexBuffer);
glBufferData(GL_ARRAY_BUFFER, numVertices*sizeof(GLfloat), vertices, GL_STATIC_DRAW);

glEnableVertexAttribArray(effect->vertCoord);        
glVertexAttribPointer(effect->vertCoord, 3, GL_FLOAT, GL_FALSE, 0, 0);

glEnableVertexAttribArray(effect->toon_vertCoord);        
glVertexAttribPointer(effect->toon_vertCoord, 3, GL_FLOAT, GL_FALSE, 0, 0);

当我加载我的第一个着色器时,我试图将顶点数据绑定到 2 个不同的着色器:

vertCoord = glGetAttribLocation(TexAndLighting, "position");

另一个着色器有:

toon_vertCoord = glGetAttribLocation(Toon, "position");

如果我彼此独立地使用着色器,它们可以正常工作,但是当我尝试在另一个之上渲染两个着色器时,它们有时会混淆模型。这是我的绘图功能的外观:

- (void) draw {
[EAGLContext setCurrentContext:context];

glBindVertexArrayOES(_vertexArray); 

effect->modelViewMatrix = mvm;
effect->numberColour = GLKVector4Make(numbers[colorSelected].r, numbers[colorSelected].g, numbers[colorSelected].b, 1);
effect->faceColour = GLKVector4Make(faceColors[colorSelected].r, faceColors[colorSelected].g, faceColors[colorSelected].b, 1);

if(selected){
    [effect drawOutline]; //this function prepares the shader
    glDrawElements(GL_TRIANGLES, numIndices, GL_UNSIGNED_SHORT, 0);
}

[effect prepareToDraw]; //same with this one
glDrawElements(GL_TRIANGLES, numIndices, GL_UNSIGNED_SHORT, 0);
}

这就是它的样子,你可以看到大多数轮廓都使用了错误的骰子,或者根本没有: 骰子的图片

完整代码的链接:http:
//pastebin.com/yDKb3wrD Dice.mm //渲染东西
http://pastebin.com/eBK0pzrK Effects.mm //着色器东西
http://pastebin.com/5LtDAk8J //我的着色器, 不应该与他们有任何关系

TL;DR:尝试使用 2 个使用相同顶点数据的不同着色器,但是在同时使用两者进行渲染时会使模型混淆,这就是我认为出错的地方,实际上很困难。

4

1 回答 1

2

你是对的,因为这是不允许的(或者说它不符合你的想法):

glEnableVertexAttribArray(effect->vertCoord);        
glVertexAttribPointer(effect->vertCoord, 3, GL_FLOAT, GL_FALSE, 0, 0);

glEnableVertexAttribArray(effect->toon_vertCoord);        
glVertexAttribPointer(effect->toon_vertCoord, 3, GL_FLOAT, GL_FALSE, 0, 0);

属性与着色器没有特别的联系。您不能告诉 OpenGL“属性N用于此着色器,而属性M用于其他着色器”。

属性只是绑定到索引,并且任何碰巧在该索引处有输入的着色器都会破坏最后绑定到该特定索引的数据。

因此,如果您有两个着色器,我们称它们为“toon”和“normal”,它们具有以下输入(这是假设的):

normal
  input vertCoord (index = 0)
  input texCoord (index = 1)

toon
  input toon_vertCoord (index = 0)
  input toon_somethingElse (index = 1)

然后当您运行此代码时:

glEnableVertexAttribArray(effect->vertCoord);        
glVertexAttribPointer(effect->vertCoord, 3, GL_FLOAT, GL_FALSE, 0, 0);

glEnableVertexAttribArray(effect->toon_vertCoord);        
glVertexAttribPointer(effect->toon_vertCoord, 3, GL_FLOAT, GL_FALSE, 0, 0);

draw_normal_object();

effect->vertCoord不再绑定到任何东西,因为toon_vertCoord具有相同的索引,并且您已经覆盖了输入指针。所以在这里你的普通着色器将从 中采样toon_vertCoord,一切都会被搞砸。

您要做的是启用/指向“普通着色器”的所有属性,绘制普通对象,然后切换到卡通着色器,启用/指向所有卡通属性,然后绘制卡通对象。

于 2012-09-04T21:37:30.523 回答